// Definition of model interface
// Copyright 2004 (C) Ralph Thomas

#ifndef MODEL_H
#define MODEL_H

#include <adobe/value.hpp>
#include <util/string.h>

namespace model {
	class receiver;
	//
	/// The model represents objects on the system and beyond.
	/// Models are usually represented by strings, until they are
	/// created by model::fromString.
	//
	class model {
	  protected:
		virtual ~model();
	  public:
		//
		// model* fromString( util::string serialized )
		//
		/// This function will take a serialized model and turn it
		/// into an actual model, loading in code where appropriate.
		///
		/// \param	serialized	a valid serialized model or
		///				URL.
		///
		/// \return	either a model instance, or NULL if the
		///		requested model couldn't be made.
		//
		static model* fromString( util::string serialized );
		//
		// model* retain() const;
		//
		/// This function increases the reference count of the
		/// model and returns a non-consted pointer. Consider this
		/// method to be like "copy".
		///
		/// \return	an unconsted pointer to this model
		//
		virtual model* retain() const = 0;
		//
		// void release()
		//
		/// This model is no longer required by something which
		/// either called model::fromString, or retained this
		/// model.
		///
		/// Note: it is a serious error to get a model (using either
		/// fromString or retain) and to not release it.
		//
		virtual void release() = 0;
		//
		// adobe::value_t getAttribute( string attrName ) const
		//
		/// Return the attribute named, if it exists. If the given
		/// attribute exists then it is returned in an attribute
		/// object, otherwise an empty attribute object is returned.
		///
		/// \param	attrName	the name of the required
		///				attribute.
		/// \return	the requested attribute, or a false attribute.
		//
		virtual adobe::value_t getAttribute( const std::string& attrName )
			const = 0;
		//
		// void setAttribute( string attrName, any value )
		//
		/// Set the specified attribute to the given value. If the
		/// named attribute doesn't exist, or is read-only then this
		/// method has no effect.
		///
		/// \param	attrName	the name of the attribute to
		///				set.
		/// \param	val		the value to set the attribute
		///				to.
		//
		virtual void setAttribute( const std::string& attrName,
			const adobe::value_t& val ) = 0;
		//
		// void subscribe( receiver* r, any data )
		//
		/// When a change happens to an attribute of this model
		/// the receiver's notify method is invoked.
		///
		/// \param	r	the reciever to notify of attribute
		///			changes.
		/// \param	data	the data to return when calling back.
		///
		/// \sa		receiver::notify
		//
		virtual void subscribe( receiver* r ) = 0;
		//
		// void unsubscribe( receiver* r )
		//
		/// The specified reciever will no longer be notified of changes
		/// to this model.
		///
		/// \param	r	the receiver to stop notifying of
		///			changes.
		//
		virtual void unsubscribe( const receiver* r ) = 0;
		//
		// void execute( string actionName, any param )
		//
		/// Some models have actions which they can perform (such as
		/// "print", or "make a copy"). This method allows those
		/// actions to be invoked.
		///
		/// \param	actionName	the name of the action to
		///				perform.
		/// \param	param		some action specific parameter.
		//
		virtual adobe::value_t execute( const std::string& actionName,
			const adobe::value_t& param ) = 0;
	};
};

#endif

